package com.dong.utils;

import lombok.AllArgsConstructor;
import lombok.Data;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;

public class TimeRangeSampler {

    /**
     * 🧱 表示一个时间区间：开始 + 结束
     * 用于传递每段采样时间段
     */
    @Data // 自动生成 getter/setter
    @AllArgsConstructor // 自动生成带全部参数的构造函数
    public static class TimeRange {
        private LocalDateTime start; // 时间段起点
        private LocalDateTime end;   // 时间段终点
    }

    /**
     * ✅ 每段采样一个数据（例如每 3 分钟取一条）
     * 用于生成趋势图、等间隔采样
     *
     * @param startTime 起始时间
     * @param endTime   结束时间
     * @param count     分段数量（即采样点数量）
     * @param queryFunc 查询函数，输入 TimeRange，返回一条数据
     * @return 每段时间返回一条数据，共 count 条
     */
    public static <T> List<T> sampleOnePerInterval(
            LocalDateTime startTime,
            LocalDateTime endTime,
            int count,
            Function<TimeRange, T> queryFunc // 函数式接口：接收 TimeRange，返回一条数据
    ) {
        List<T> result = new ArrayList<>();

        // 计算整个时间段的总时长
        Duration total = Duration.between(startTime, endTime);

        // 计算每段的时间间隔
        Duration interval = total.dividedBy(count);

        // 遍历每段时间区间，调用 queryFunc 查询一条数据
        for (int i = 0; i < count; i++) {
            // 当前段的起止时间
            LocalDateTime intervalStart = startTime.plus(interval.multipliedBy(i));
            LocalDateTime intervalEnd = (i == count - 1) ? endTime : intervalStart.plus(interval);

            // 构造当前时间段对象并传给查询函数
            T data = queryFunc.apply(new TimeRange(intervalStart, intervalEnd));

            // 如果返回非空数据则加入结果列表
            if (data != null) {
                result.add(data);
            }
        }

        return result;
    }

    /**
     * ✅ 每段返回多个数据（例如每段都查出所有数据）
     * 用于展示详细数据、明细表、分段聚合等场景
     *
     * @param startTime 起始时间
     * @param endTime   结束时间
     * @param count     分段数量
     * @param queryFunc 查询函数，输入 TimeRange，返回一个 List<T>
     * @return 所有段数据累加的总结果
     */
    public static <T> List<T> sampleListPerInterval(
            LocalDateTime startTime,
            LocalDateTime endTime,
            int count,
            Function<TimeRange, List<T>> queryFunc
    ) {
        List<T> result = new ArrayList<>();

        // 计算总时间长度
        Duration total = Duration.between(startTime, endTime);
        // 每段时间长度
        Duration interval = total.dividedBy(count);

        // 遍历每段时间
        for (int i = 0; i < count; i++) {
            LocalDateTime intervalStart = startTime.plus(interval.multipliedBy(i));
            LocalDateTime intervalEnd = (i == count - 1) ? endTime : intervalStart.plus(interval);

            // 查询每段的所有数据
            List<T> list = queryFunc.apply(new TimeRange(intervalStart, intervalEnd));

            // 如果非空，则全部加入结果
            if (list != null && !list.isEmpty()) {
                result.addAll(list);
            }
        }

        return result;
    }
}
